package com.ww.springboot.boot.thread.study.base.countdownlatch;

import com.ww.springboot.boot.thread.study.base.lock.aqs.util.ThreadPrintUtil;
import lombok.SneakyThrows;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * 描述：
 *  CountDownLatch 设计思路:
 *  先将state 设置为某个数值 获取await()获取资源 没获取到则一直自旋 直到获取到为止
 *
 *  countDown() 每次将state值减1 自旋直到减1成功后触发释放锁逻辑 让等待节点尝试获取锁
 *
 *  ww_m 怎么保证countDown的并发?不断自旋 直到cas成功减1为止
 *
 *  CountDownLatch是主线程一直等待子线程执行 阻塞是在主线程中  也可以阻塞子线程 主线程释放锁
 *
 *  countDownLatch : 线程A count 决定线程B 解锁 -- 共进退 但真正的后续逻辑在其他线程
 *  CyclicBarrier : 线程A 线程B 一起决定 自己是否往下走 -- 共进退
 *
 * @author wanwei
 * @since 2021-06-26 11:21
 */
public class Demo1 {

    //将state设置为 相应的数量
    public static final CountDownLatch countDownLatch = new CountDownLatch(2);

    public static void main(String[] args) throws InterruptedException {
        System.out.println("开始:" + System.currentTimeMillis());
        Thread thread1 = new Thread(new Runnable() {
            @SneakyThrows
            @Override
            public void run() {
                TimeUnit.SECONDS.sleep(10);
                //使用CAS 对state进行递减
                countDownLatch.countDown();
            }
        });
        thread1.start();

        Thread thread2 = new Thread(new Runnable() {
            @SneakyThrows
            @Override
            public void run() {
                TimeUnit.SECONDS.sleep(10);
                countDownLatch.countDown();
            }
        });
        thread2.start();

        new Thread(()->{
            try {
                countDownLatch.await();
                ThreadPrintUtil.sout("解锁");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();


        new Thread(()->{
            try {
                countDownLatch.await();
                ThreadPrintUtil.sout("解锁");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();



        System.out.println("结束:" + System.currentTimeMillis());
    }
}
